package com.darly.std.queue.masterwoker;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Description TODO:Master-Worker设计模式介绍
 * Master-Worker模式是常用的并行设计模式。核心思想是，系统由两个角色组成，Master和Worker，Master负责接收和分配任务，
 * Worker负责处理子任务。任务处理过程中，Master还负责监督任务进展和Worker的健康状态；Master将接收Client提交的任务，
 * 并将任务的进展汇总反馈给Client。各角色关系如下图
 * -----------------------client-------------------
 * *************************||*********************
 * *************************||*********************
 * -----------------------master-------------------
 * ***********************||||||*******************
 * ********************||***||***||****************
 * ****************||*******||********||***********
 * -----------Worker------Worker------Worker-------
 * Master-Worker模式满足于可以将大任务划分为小任务的场景，是一种分而治之的设计理念。通过多线程或者多进程多机器的模式，
 * 可以将小任务处理分发给更多的CPU处理，降低单个CPU的计算量，通过并发/并行提高任务的完成速度，提高系统的性能。
 * Package com.darly.std.queue.masterwoker
 * Author fronchdarly
 * Date 2021/8/4 10:42 AM
 * Where: 陕西西安
 * How:
 */
public class Master {
    //1:应该有一个承载任务的集合
    private ConcurrentLinkedQueue<Mession> workQueue = new ConcurrentLinkedQueue<Mession>();
    //2:使用hashmap去承载所有的worker对象 ThreadName------Worker
    private HashMap<String, Thread> workers = new HashMap<>();
    //3:使用一个容器承载每一个worker并行执行任务的结果集
    private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<String, Object>();

    //4:构造方法
    public Master(Worker worker, int workerCount) {
        worker.setWorkQueue(workQueue);
        worker.setResultMap(resultMap);
        for (int i = 0; i < workerCount; i++) {
            workers.put("子节点" + i, new Thread(worker));
        }

    }

    //5:提交方法
    public void submit(Mession mession) {
        workQueue.add(mession);
    }

    //6:需要有一个执行的方法(启动应用程序 让所有的worker工作)
    public void execute() {
        //遍历workers 分别去执行每一个worker
        for (Map.Entry<String, Thread> entry : workers.entrySet()) {
            if (entry.getValue() != null) {
                entry.getValue().start();
            }
        }
    }

    //判断所有的worker是否执行完毕
    public boolean isCompleted() {
        for (Map.Entry<String, Thread> entry : workers.entrySet()) {
            if (entry.getValue() != null && entry.getValue().getState() != Thread.State.TERMINATED) {
                return false;
            }
        }
        return true;
    }

    //计算最终的结果集
    public int getResult() {
        int result = 0;
        for (Map.Entry<String, Object> entry : resultMap.entrySet()) {
            if (entry.getValue() != null) {
                result++;
            }
        }
        return result;
    }
}
